﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using MySql.Simple.Mapper.Commands.Rows;
using MySql.Simple.Mapper.Structures;

namespace MySql.Simple.Mapper.Patterns
{
    /// <summary>
    /// Base repository class to provide basic CRUD operations
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class Repository<T> where T : new()
    {
        /// <summary>
        /// Gets the databse connection.
        /// </summary>
        /// <value>The connection.</value>
        protected virtual Connection CreatePooledConnection()
        {
            return Connection.Create();
        }

        /// <summary>
        /// Creates the specified row.
        /// </summary>
        /// <param name="row">The row.</param>
        /// <returns></returns>
        protected object Insert(T row)
        {
            return InsertCommand.Execute(row, CreatePooledConnection());;
        }

        /// <summary>
        /// Reads the specified id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        protected T SelectOne(object id)
        {
            return SelectOneCommand.Execute<T>(id, CreatePooledConnection());
        }

        /// <summary>
        /// Selects all.
        /// </summary>
        /// <param name="ids">The ids.</param>
        /// <returns></returns>
        protected IList<T> SelectList(IEnumerable<object> ids)
        {
            var results = new List<T>();

            foreach (var id in ids)
            {
                results.Add(SelectOne(id));
            }

            return results;
        }

        /// <summary>
        /// Selects the list.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <returns></returns>
        protected IList<T> SelectList(Expression<Func<T, object>> expression)
        {
            return SelectListCommand.Execute(expression, CreatePooledConnection());
        }

        /// <summary>
        /// Returns all the rows in the underlying database table
        /// </summary>
        /// <returns></returns>
        protected IList<T> SelectAll()
        {
            return SelectAllCommand.Execute<T>(CreatePooledConnection());
        }

        /// <summary>
        /// Updates the specified row.
        /// </summary>
        /// <param name="row">The row.</param>
        protected void Update(T row)
        {
            UpdateCommand.Update(row, CreatePooledConnection());
        }

        /// <summary>
        /// Deletes the specified id.
        /// </summary>
        /// <param name="id">The id.</param>
        protected void Delete(object id)
        {
            DeleteCommand.Execute<T>(id, CreatePooledConnection());
        }
    }
}